package cn.est.controller;

import cn.est.config.WxConfig;
import cn.est.constants.Constants;
import cn.est.dto.Result;
import cn.est.exceptions.RedisException;
import cn.est.exceptions.TokenProtectedException;
import cn.est.pojo.Users;
import cn.est.service.TokenService;
import cn.est.service.UsersService;
import cn.est.utils.HttpClientUtil;
import cn.est.utils.RedisUtil;
import cn.est.utils.ResultUtils;
import cn.est.vo.TokenVo;
import cn.est.vo.WxTokenVo;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName WxController
 * @Description TODO
 * @Author yaozhaobao
 * @Date 2021/4/7 11:25
 * @Version 1.0
 **/
@Api("wx")
@RestController
@RequestMapping("/api/user")
public class WxController {
    @Autowired
    WxConfig wxConfig;

    @Autowired
    UsersService usersService;

    @Autowired
    TokenService tokenService;

    @Autowired
    RedisUtil redisUtil;

    @ApiOperation(value = "微信登录请求",produces="application/json",notes ="微信登录请求")
    //1.跳转到二维码授权页面的接口
    @GetMapping("/wxlogin")
    public void redirectWx(HttpServletResponse response) throws IOException {
        StringBuffer url=new StringBuffer("https://open.weixin.qq.com/connect/qrconnect?appid=").
                 append(wxConfig.getAppid())
                .append("&redirect_uri=")
                .append(URLEncoder.encode("http://localhost:8080/est/api/user/callback"))
                .append("&response_type=code&scope=snsapi_login&state=hellowx#wechat_redirect");
        response.sendRedirect(url.toString());
    }


    //2.用户授权后，回调的接口
    @GetMapping("/callback")
    public Result callback(String code, String state){

        if(state == null || !state.equals("hellowx")){
            return ResultUtils.returnFail("非法请求");
        }

        //带着临时票据继续请求微信接口
        System.out.println(code);
        StringBuffer stringBuffer = new StringBuffer("https://api.weixin.qq.com/sns/oauth2/access_token?appid=");
        stringBuffer.append(wxConfig.getAppid());
        stringBuffer.append("&secret=");
        stringBuffer.append(wxConfig.getAppsecret());
        stringBuffer.append("&code=");
        stringBuffer.append(code);
        stringBuffer.append("&grant_type=authorization_code");
        String response= HttpClientUtil.doGet(stringBuffer.toString());
        JSONObject jsonObject=JSONObject.parseObject(response);

        //1、判断接口能否正确的获取返回值：accesstoken
        if(jsonObject.get("errorCode") != null){
            //说明出错，调用接口出错
            return ResultUtils.returnFail((String) jsonObject.get("errmsg"),(String) jsonObject.get("errorCode"));
        }

        //2、判断当前openId是否存在在数据中，如果没有就进行注册
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("openId",jsonObject.get("openid"));
        List<Users> usersList = usersService.getUsersListByMap(map);
        Users user = null;
        if (usersList.size() == 0 || usersList == null){
            user =new Users();
            user.setOpenId((String) jsonObject.get("openid"));
            user.setIsAuthentication(0);
            user.setCreatdTime(new Date());
            user.setIsDelete(0);
            usersService.qdtxAddUsers(user);
        }else{
            user = usersList.get(0);
        }

        //3、生成token，保存用户的登录信息
        TokenVo tokenVo = tokenService.genenrateToken(user);

        //4、保存token到redis中
        tokenService.saveToken(tokenVo.getToken(),user);

        //5、返回token
        WxTokenVo wxTokenVo =new WxTokenVo();
        wxTokenVo.setTokenVo(tokenVo);
        wxTokenVo.setAccessToken((String) jsonObject.get("access_token"));
        wxTokenVo.setRefreshToken((String) jsonObject.get("refresh_token"));
        wxTokenVo.setExpiresTime(jsonObject.get("expires_in").toString());
        wxTokenVo.setOpenId((String) jsonObject.get("openid"));
        //把微信token放入redis中
        redisUtil.set("wx:"+tokenVo.getToken(),wxTokenVo, Constants.Token.WX_VALID_TIME);
        return ResultUtils.returnDataSuccess(tokenVo);
    }

    //获取用户信息的接口
    @PostMapping("/info")
    public Result getUserInfo(@RequestParam String token) throws UnsupportedEncodingException {
        //1、首先查看在redis中是否存在此token
        if (redisUtil.get(token) == null){
            return ResultUtils.returnFail("token无效","20004");
        }

        //2、如果有就根据这个token取出数据中携带的accesstoken和openid
        String accessToken = ((WxTokenVo)(redisUtil.get("wx:"+token))).getAccessToken();
        String openId = ((WxTokenVo)(redisUtil.get("wx:"+token))).getOpenId();

        //4、然后拼接url继续请求接口
        StringBuffer stringBuffer =new StringBuffer("https://api.weixin.qq.com/sns/userinfo?access_token=");
        stringBuffer.append(accessToken);
        stringBuffer.append("&openid=");
        stringBuffer.append(openId);
         String response= HttpClientUtil.doGet(stringBuffer.toString());
        JSONObject jsonObject= JSONObject.parseObject(response);

        //5、判断是否正确获取信息
        if(jsonObject.get("errcode")!=null){
            return ResultUtils.returnFail(jsonObject.get("errmsg").toString(),jsonObject.get("errcode").toString());
        }

        //6、然后再根据openid去数据库查找匹配对象（有此对象就直接使用，没有就把这个对象插入数据库）
        Map<String,Object> map = new HashMap<String,Object>();
        map.put("openId",(String) jsonObject.get("openid"));
        List<Users> userList=usersService.getUsersListByMap(map);
        Users user=userList.get(0);
        if(user.getName()==null||user.getName().equals("")){
            String nickname=new String(jsonObject.get("nickname").toString().getBytes("ISO-8859-1"),"UTF-8");
            user.setName(nickname);
            user.setSex(Integer.parseInt(jsonObject.get("sex").toString()));
            user.setFaceUrl(jsonObject.get("headimgurl").toString());
            usersService.qdtxModifyUsers(user);
        }

        //7、返回用户信息
        return  ResultUtils.returnDataSuccess(user);
    }

    /**
     * accessToken的置换
     */
    @ApiOperation(value = "wx置换token",produces="application/json",notes ="wx置换token")
    @PostMapping("/refresh")
    public Result refreshWechatToken(@RequestParam String token) throws RedisException, TokenProtectedException {
        //1、先判断此token是否有效，如果到了置换期就先生成新的token
        TokenVo tokenVo = tokenService.refreshToken(token);
        //2、获取微信refreshtoken
        WxTokenVo wxTokenVo = (WxTokenVo) redisUtil.get("wx:"+token);
        //3、使用refreshtoken请求接口刷新获取新的accesstoken
        StringBuffer stringBuffer=new StringBuffer("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=");
        stringBuffer.append(wxConfig.getAppid());
        stringBuffer.append("&grant_type=");
        stringBuffer.append("refresh_token");
        stringBuffer.append("&refresh_token=");
        stringBuffer.append(wxTokenVo.getRefreshToken());
        String response=HttpClientUtil.doGet(stringBuffer.toString());
        JSONObject jsonObject = JSONObject.parseObject(response);

        //判断是否正确获取信息
        if(jsonObject.get("error")!=null){
            return ResultUtils.returnFail(jsonObject.get("errmsg").toString(),jsonObject.get("error").toString());
        }

        //将获取到的refreshtoken和新的accesstoken放入WxTokenVo对象中
        wxTokenVo.setAccessToken(jsonObject.get("access_token").toString());
        wxTokenVo.setRefreshToken(jsonObject.get("refresh_token").toString());
        //redisUtil.expire("wx:"+token,30);  //设置微信token的失效时间，以便测试
        //把新的WxTokenVo对象放入redis中
        redisUtil.set("wx:"+tokenVo.getToken(),wxTokenVo,Constants.Token.WX_VALID_TIME);

        //把新的token返回
        return ResultUtils.returnDataSuccess(tokenVo);
    }
}
